#pragma once
#include "exchange.h"
#include "queue.h"
#include "bind.h"
#include "message.h"

namespace ns_virtual
{
    using namespace ns_log;
    using namespace ns_util;
    using namespace ns_proto;
    using namespace ns_exchange;
    using namespace ns_queue;
    using namespace ns_bind;
    using namespace ns_message;

    class VirtualHost
    {
    public:
        VirtualHost(const string &path, const string &dbfile)
            : _emp(make_shared<ExchangeManage>(dbfile)),
              _qmp(make_shared<QueueManage>(dbfile)),
              _bmp(make_shared<BindManage>(dbfile)),
              _mmp(make_shared<MessageManage>(path))
        {
            // 数据恢复
            // 获取所有队列名称，根据队列名称进行消息数据恢复
            auto all_que = _qmp->get_all();
            for (auto &qp : all_que)
            {
                _mmp->init_msg_queue(qp.first);
            }
        }

        // 声明、删除交换机
        void declare_exchange(const string &ename, const ExchangeType &type,
                              const bool &IsDurable,
                              const bool &auto_delete,
                              const google::protobuf::Map<std::string, std::string> &args)
        {
            _emp->declare_exchange(ename, type, IsDurable, auto_delete, args);
        }
        void delete_exchange(const string &ename)
        {
            _emp->delete_exchange(ename);
            // 删除交换机时 同时也要将交换机绑定数据删除
            _bmp->delete_exchange(ename);
        }

        // 声明、删除队列
        void declare_queue(const string &name,
                           const bool &IsDurable,
                           const bool &exclusive,
                           const bool &auto_delete,
                           const google::protobuf::Map<std::string, std::string> &args)
        {
            _qmp->declare_queue(name, IsDurable, exclusive, auto_delete, args);
            // 同时还要创建队列消息文件
            _mmp->init_msg_queue(name);
        }
        void delete_queue(const string &qname)
        {
            _qmp->delete_queue(qname);
            // 同时还要删除队列消息文件数据
            _mmp->destroy_msg_queue(qname);
            // 同时要删除队列绑定信息
            _bmp->delete_queue(qname);
        }
        // 获取所有队列信息
        unordered_map<string, Queue::ptr> allQueues()
        {
            return _qmp->get_all();
        }

        // 声明、删除交换机与队列的相关绑定信息
        void declare_bind(const string &ename, const string &qname,
                          const string &binding_key)
        {
            // 绑定信息是否进行持久化同时取决于交换机与队列
            Exchange::ptr ep = _emp->select_exchange(ename);
            Queue::ptr qp = _qmp->select_queue(qname);
            if (ep.get() == nullptr || qp.get() == nullptr)
            {
                LOG(WARNING) << "交换机或队列不存在" << endl;
                return;
            }
            _bmp->bind(ename, qname, binding_key, ep->_IsDurable && qp->_IsDurable);
        }
        void delete_bind(const string &ename, const string &qname)
        {
            _bmp->unbind(ename, qname);
        }
        // 获取交换机所有绑定信息
        const QueueBindMapPtr exchange_binds(const string &ename)
        {
            return _bmp->get_exchange_bind(ename);
        }
        // 获取指定交换机
        const Exchange::ptr select_exchange(const string &ename)
        {
            return _emp->select_exchange(ename);
        }

        // 新增、获取队首、确认消息
        void insert_msg(const string &qname, const ns_proto::Attributes *attribute,
                        const string &body)
        {
            Queue::ptr qp = _qmp->select_queue(qname);
            if (qp.get() == nullptr)
            {
                LOG(WARNING) << "该队列不存在，无法添加消息" << endl;
                return;
            }
            DeliverMode qdurable = qp->_IsDurable ? DURABLE : UNDURABLE;
            _mmp->insert_msg(qname, attribute, body, qdurable);
        }
        ns_message::MessagePtr que_front_msg(const string &qname)
        {
            return _mmp->front(qname);
        }
        void comfirm_msg(const string &qname, const string &msg_id)
        {
            _mmp->comfirm_msg(qname, msg_id);
        }

        //------------------------------------------测试部分
        // 判断交换机是否存在
        bool exist_exchange(const string &ename)
        {
            return _emp->exist(ename);
        }
        // 判断队列是否存在
        bool exist_queue(const string &qname)
        {
            return _qmp->exist(qname);
        }
        // 判断绑定信息是否存在
        bool exist_binding(const string &ename, const string &qname)
        {
            return _bmp->exist(ename, qname);
        }
        // 清除交换机
        void clear()
        {
            _emp->clear();
            _qmp->clear();
            _bmp->clear();
            _mmp->clear();
        }

    private:
        shared_ptr<ExchangeManage> _emp;
        shared_ptr<QueueManage> _qmp;
        shared_ptr<BindManage> _bmp;
        shared_ptr<MessageManage> _mmp;
    };

}